/*************************************************************************
 * Filename:    QueueManager.c
 * Description: Manages the various process queues.
 * Group 2:     nachOS
 * Authors:     Ying Wang
 *              Daniel Fairweather
 *              Jan Durakiewicz
 * Class:       CSE 325
 * Instructor:  Mr. Duggan
 * Assignment:  Lab #3 Scheduler
 * Assigned:    Feburary 12, 2013
 * Due:         Feburary 26, 2013
 *************************************************************************/
#include "QueueManager.h"



void initalizeQueueManager(){
    int i;
    
    /* Set all head and tail pointers to NULL. */
    for(i = 0; i < NUM_QUEUES; i++){
        queues[i].head = NULL;
        queues[i].tail = NULL;
    }
}



process_queue* getQueue(int qid){
    if((qid < NUM_QUEUES) && (qid >=0 )){
        return &queues[qid];
    }
    else{
        return NULL;
    }
}



process_control_block* enqueue(int qid, process_control_block* process){
    process_queue* queue = &queues[qid];
    
    /* If the process is NULL, return NULL. */
    if(process == NULL){
        return(NULL);
    }

    process->previous = queue->tail;
    process->next = NULL;

    /* If this is the first queue item in the queue, point the head to it. */
    if(queue->head == NULL){
        queue->head = process;
    }
    /* If this is not the first queue item, make the previous tail point to the new queue item. */
    else{
        queue->tail->next = process;
    }

    queue->tail = process;
    return(process);
}



process_control_block* dequeue(int qid){
    process_queue* queue = &queues[qid];
    process_control_block* process;

    /* If the queue is empty, return an error. */
    if(queue->head == NULL){
        return(NULL);
    }
    /* If the queue has only one element, we need to point the tail to 0 as well. */
    else if(queue->head == queue->tail){
        queue->tail = NULL;
    }

    /* Remove the process from the queue. */
    process = queue->head;
    queue->head = queue->head->next;
    return(process);
}



process_control_block* delqueue(int qid, int pid){
    process_queue* queue = &queues[qid];
    process_control_block* process = queue->head;

    /* Search for the process, and delete it if found. */
    while(process != NULL){
        if(process->pid == pid){
            /* If this is the head process, just do a dequeue. */
            if(process == queue->head){
                return(dequeue(qid));
            }
            /* If this is the tail process, make sure the previous item points to NULL, then fix the tail. */
            if(process == queue->tail){
                process->previous->next = NULL;
                queue->tail = process->previous;
            }
            /* If this is a middle process, just swap the neighbors pointers. */
            else{
                process->previous->next = process->next;
                process->next->previous = process->previous;
            }
            
            return(process);
        }
        process = process->next;
    }

    /* If the process could not be found, return NULL. */
    return(NULL);
}



process_control_block* search(int qid, int pid){
    process_queue* queue = &queues[qid];
    process_control_block* process = queue->head;

    /* Search for the process within this queue. */
    while(process != NULL){
        if(process->pid == pid){
            return(process);
        }
        process = process->next;
    }

    /* If nothing was found return NULL. */
    return(NULL);
}



int isUniquePID(int pid){
    if(search(0, pid) == NULL && search(1, pid) == NULL && search(2, pid) == NULL && search(3, pid) == NULL && search(4, pid) == NULL){
        return(1);
    }
    return(0);
}



int isEmptyQueue(int qid){
    process_queue* queue = &queues[qid];

    /* If the head is NULL, return true. */
    if(queue->head == NULL){
        return(1);
    }

    /* If the queue isn't empty, return false. */
    return(0);
}